﻿#ifndef _INITERNAL_P_H_H_
#define _INITERNAL_P_H_H_
#include "kernel/OgreStdHeaders.h"
#include "kernel/unicodestring.h"
#include "udatabase/dll_cfg.h"

#if defined(__OS_WIN__)
#include <hash_set>
#include <hash_map>
#else
#include <tr1/unordered_map>
using std::tr1::unordered_map;
#endif

namespace FD{
	namespace Utility{
		namespace DB{

			template<class K,class V>
			class CSqlHash
			{
			public:
				void clear() { hash.clear(); }

				K key(V val) const
				{

#if defined(__OS_WIN__)
					typename stdext::hash_map<K,V>::const_iterator iter;
#else
					typename unordered_map<K,V>::const_iterator iter;
#endif

					for(iter=hash.begin();iter!=hash.end();++iter)
					{
						if(iter->second==val)
							return iter->first;
					}
					return K();
				}
				V value(K k) const
				{
#if defined(__OS_WIN__)
					typename stdext::hash_map<K,V>::const_iterator iter;
#else
					typename unordered_map<K,V>::const_iterator iter;
#endif

					if (hash->size == 0 || (iter=hash.find(k))==hash.end()) {
						return V();
					} else {
						return iter->second;
					}
				}
				V value(K k, V def) const
				{
#if defined(__OS_WIN__)
					typename stdext::hash_map<K,V>::const_iterator iter;
#else
					typename unordered_map<K,V>::const_iterator iter;
#endif

					if (hash.size() == 0 || (iter=hash.find(k))==hash.end()) {
						return def;
					} else {
						return iter->second;
					}
				}
				V& operator[](K k)
				{
					return hash[k];
				}
				bool isEmpty()
				{
					return hash.empty();
				};

			private:
				//FD::Kernel::hashmap<K,V> hash;
#if defined(__OS_WIN__)
				stdext::hash_map<K,V> hash;
#else
				unordered_map<K,V> hash;
#endif
			};

#ifdef __OS_LINUX__
			struct hash_func  //hash 函数
			{
				size_t operator()(const FD::Kernel::FdUnicodeString &s) const
				{
					return (UINT64)s.c_str();
				}
			};

			class CSqlHash_UnicodeStr
			{
			public:
				void clear() { hash.clear(); }

				FD::Kernel::FdUnicodeString key(int val) const
				{
					typename unordered_map<FD::Kernel::FdUnicodeString, int>::const_iterator iter;

					for(iter=hash.begin();iter!=hash.end();++iter)
					{
						if(iter->second==val)
							return iter->first;
					}
					return FD::Kernel::FdUnicodeString();
				}
				int value(FD::Kernel::FdUnicodeString k) const
				{
					typename unordered_map<FD::Kernel::FdUnicodeString, int>::const_iterator iter;

					if (hash.size() == 0 || (iter=hash.find(k))==hash.end()) {
						return int();
					} else {
						return iter->second;
					}
				}
				int value(FD::Kernel::FdUnicodeString k, int def) const
				{
					typename unordered_map<FD::Kernel::FdUnicodeString, int>::const_iterator iter;

					if (hash.size() == 0 || (iter=hash.find(k))==hash.end()) {
						return def;
					} else {
						return iter->second;
					}
				}
				int& operator[](FD::Kernel::FdUnicodeString k)
				{
					return hash[k];
				}
				bool isEmpty()
				{
					return hash.empty();
				};

			private:
				unordered_map<FD::Kernel::FdUnicodeString, int, hash_func> hash;
			};

#endif
			static FD::Kernel::FdMultiByteString unicodeToUtf8(const FD::Kernel::FdUnicodeString &unicode)
			{
				// 计算UTF8的长度
				UINT32 i,j,ret;
				for(i=0,j=0;i<unicode.size();i++)
				{
					ret=0;
					if(unicode[i]<=0x007f)
					{
						ret=1;
					}
					else if(unicode[i]<=0x07ff)
					{
						ret=2;
					}
					else if(unicode[i]<=0xffff)
					{
						ret=3;
					}
					j+=ret;
				}
				int Len = j;
				////////////////////////
				CHAR *utf8 = new CHAR[Len+1];

				for(i=0,j=0;i<unicode.size();i++)
				{
					ret=0;
					if(utf8!=0)
					{
						unsigned char *pChar=(unsigned char *)&unicode[i];

						if(unicode[i]<=0x007f)
						{
							utf8[j]=pChar[0];
							ret=1;
						}
						else if(unicode[i]<=0x07ff)
						{
							if(j  < (UINT32)Len )
							{
								utf8[j]=0xc0|(pChar[1])<<2|(pChar[0]>>6);
								utf8[j+1]=0x80|(pChar[0]&0x3f);
								ret=2;
							}
						}
						else if(unicode[i]<=0xffff)

						{
							if(j < (UINT32)Len && (j < ((UINT32)Len - 1)) )
							{
								utf8[j] = 0xe0|(pChar[1]>>4);
								utf8[j+1] = 0x80|((pChar[1]&0x0f)<<2)|(pChar[0]>>6);
								utf8[j+2] = 0x80|(pChar[0]&0x3f);
								ret=3;
							}
						}
						j+=ret;
					}
				}

				utf8[Len] = '\0';
				FD::Kernel::FdMultiByteString str(utf8);
				delete[] utf8;

				return str;
			}



		} // namespace Database
	}
}


#endif //_INITERNAL_P_H_H_
